package com.ihm.labyrinth.levels;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import com.ihm.labyrinth.LabMainActivity;
import com.ihm.labyrinth.SettingsActivity;
import com.ihm.labyrinth.listener.GameListener;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;

/**
 * Parser du tutoriel : http://developer.android.com/training/basics/network-ops/xml.html
 * @author Christophe
 *
 */
public class LevelManager {

	private LabMainActivity context;
	
	private static final String ns = null;
	
	private List<Level> levels = new ArrayList<Level>();
	
	int actualPosition;
	
	int maxLevel;
	
	public LevelManager(LabMainActivity context, int actualPosition, int maxLevel){
		this.context = context;
		this.actualPosition = actualPosition;
		this.maxLevel = maxLevel;
	}

	public Level getActualLevel(){
		return levels.get(actualPosition);
	}
	
	public Level nextLevel(){
		if(actualPosition < levels.size()){
			actualPosition++;
			if(actualPosition > maxLevel)
				maxLevel = actualPosition;
			return levels.get(actualPosition);
		}
		else
			return null;
	}

	public void parseLevels() throws XmlPullParserException, IOException {
		
		InputStream in = context.getResources().getAssets().open("Levels.xml");
		
		try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(in, null);
            parser.nextTag();
            levels = readFeed(parser, context.getTargetFPS());
        } finally {
            in.close();
        }
    }
	
	private List<Level> readFeed(XmlPullParser parser, int fps) throws XmlPullParserException, IOException {
	    List<Level> levels = new ArrayList<Level>();

	    parser.require(XmlPullParser.START_TAG, ns, "maps");
	    while (parser.next() != XmlPullParser.END_TAG) {
	        if (parser.getEventType() != XmlPullParser.START_TAG) {
	            continue;
	        }
	        String name = parser.getName();
	        // Starts by looking for the entry tag
	        if (name.equals("level")) {
	        	Level level = readLevel(parser, fps);
	        	if(level != null)
	        		levels.add(level);
	        	else
	        		Log.e("LEVEL", "Wrong Format");
	        } else {
	            skip(parser);
	        }
	    }
	    return levels;
	}


	private Level readLevel(XmlPullParser parser, int fps) throws NumberFormatException, XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, ns, "level");
	    String name = "";
	    String filename = "";
	    int shootCycle = 0;
	    int position = -1;
	    int height = -1;
	    int width = -1;
	    
	    while (parser.next() != XmlPullParser.END_TAG) {
	        if (parser.getEventType() != XmlPullParser.START_TAG) {
	            continue;
	        }
	        String tagname = parser.getName();
	        if (tagname.equals("position")) {
	            position = readInt(parser, tagname);
	        } else if (tagname.equals("filename")) {
	            filename = readString(parser, tagname);
	        } else if (tagname.equals("name")) {
	            name = readString(parser, tagname);
	        } else if (tagname.equals("shootCycle")) {
	            shootCycle = readInt(parser, tagname);
	        } else if (tagname.equals("mapHeight")) {
	            height = readInt(parser, tagname);
	        } else if (tagname.equals("mapWidth")) {
	            width = readInt(parser, tagname);
	        }else {
	            skip(parser);
	        }
	    }
	    if(position != -1 && name!= "" && filename != "" && height != -1 && width != -1){
	    	return new Level(position, name, shootCycle* (fps/2), filename, height, width);
	    }
	    else
	    	return null;
	}

	private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
		if (parser.getEventType() != XmlPullParser.START_TAG) {
	        throw new IllegalStateException();
	    }
	    int depth = 1;
	    while (depth != 0) {
	        switch (parser.next()) {
	        case XmlPullParser.END_TAG:
	            depth--;
	            break;
	        case XmlPullParser.START_TAG:
	            depth++;
	            break;
	        }
	    }
		
	}

	private String readString(XmlPullParser parser, String tagName) throws XmlPullParserException, IOException {
		parser.require(XmlPullParser.START_TAG, ns, tagName);
		 String text = readText(parser);
		 parser.require(XmlPullParser.END_TAG, ns, tagName);
		 return text;
	}
	
	private int readInt(XmlPullParser parser,  String tagName) throws XmlPullParserException, IOException, NumberFormatException {
		String number = readString(parser, tagName);
		return Integer.parseInt(number);
	}
	
	
	// For the tags title and summary, extracts their text values.
	private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
	    String result = "";
	    if (parser.next() == XmlPullParser.TEXT) {
	        result = parser.getText();
	        parser.nextTag();
	    }
	    return result;
	}

	public List<Level> getLevels() {
		return levels;
	}

	public void setLevels(List<Level> levels) {
		this.levels = levels;
	}

	public int getActualPosition() {
		return actualPosition;
	}

	public void setActualPosition(int actualPosition) {
		this.actualPosition = actualPosition;
	}
	
	public InputStream getMapStream() throws IOException{
		return context.getAssets().open("level/" + getActualLevel().getFilename());
	}

	public Bundle getLevelBundle() {
		Bundle levelBundle = new Bundle();
		for(int i = 0; i <= maxLevel; i++){
			
			levelBundle.putString(""+levels.get(i).getPosition(), levels.get(i).getName());
		}
		//levelBundle.putInt(SettingsActivity.KEY_ACTUAL_LEVEL, actualPosition);
		return levelBundle;
	}

	public int getMaxLevel() {
		return maxLevel;
	}

	public void setMaxLevel(int maxLevel) {
		this.maxLevel = maxLevel;
	}
}
